// test_allocation.c
#include "test_framework.h"
#include "../hisi_l0_mem_pool.h"
#include "test_common.h"
#include "test_registration.h"

/**
 * test_small_object_allocation - Tests allocation of small objects (32-4096 bytes)
 * 
 * This test verifies:
 * 1. Allocation of small objects using the Fix Allocator cache system
 * 2. Memory accessibility by writing test patterns
 * 3. No memory overlap between consecutive allocations
 * 4. Proper cleanup of allocated memory
 * 
 * Tests Fix Allocator allocator functionality for objects <= MAX_FIX_ALLOCATOR_SIZE
 */
static int test_small_object_allocation(struct seq_file *m)
{
    struct test_context *ctx = get_test_context();
    void *ptr1, *ptr2;
    size_t test_sizes[] = {32, 64, 128, 256, 512, 1024, 2048, 4096};
    int i;
    int passed = 0, total = 0;
    
    for (i = 0; i < ARRAY_SIZE(test_sizes); i++) {
        total++;
        ptr1 = l0_kmalloc(test_sizes[i], ctx->test_node_id);
        
        if (ptr1) {
            // Verify memory is accessible
            memset(ptr1, 0xAA, test_sizes[i]);
            
            ptr2 = l0_kmalloc(test_sizes[i], ctx->test_node_id);
            if (ptr2) {
                memset(ptr2, 0x55, test_sizes[i]);
                
                // Simple overlap check
                if (!((unsigned long)ptr1 >= (unsigned long)ptr2 && 
                      (unsigned long)ptr1 < ((unsigned long)ptr2 + test_sizes[i])) &&
                    !((unsigned long)ptr2 >= (unsigned long)ptr1 && 
                      (unsigned long)ptr2 < ((unsigned long)ptr1 + test_sizes[i]))) {
                    TEST_PASS_DEBUG(m, "Size %zu: No overlap detected", test_sizes[i]);
                    passed++;
                } else {
                    TEST_FAIL(m, "Size %zu: Memory overlap detected", test_sizes[i]);
                }
                
                l0_kfree(ptr2);
            } else {
                TEST_FAIL(m, "Size %zu: Second allocation failed", test_sizes[i]);
            }
            l0_kfree(ptr1);
        } else {
            TEST_FAIL(m, "Size %zu: Allocation failed", test_sizes[i]);
        }
    }
    
    TEST_END(m, "Passed: %d/%d tests", passed, total);
    return (passed == total) ? 0 : -1;
}

/**
 * test_large_object_allocation - Tests allocation of large objects (>8KB)
 * 
 * This test verifies:
 * 1. Allocation of large objects that bypass Fix Allocator cache and use flex_allocator directly
 * 2. Memory accessibility for large allocations
 * 3. Proper cleanup of large allocated memory blocks
 * 
 * Tests flex_allocator allocation for objects > MAX_FIX_ALLOCATOR_SIZE
 */
static int test_large_object_allocation(struct seq_file *m)
{
    struct test_context *ctx = get_test_context();
    void *ptr;
    size_t large_sizes[] = {8193, 16384, 32768, 65536, 131072};
    int i;
    int passed = 0, total = 0;
    
    for (i = 0; i < ARRAY_SIZE(large_sizes); i++) {
        total++;
        ptr = l0_kmalloc(large_sizes[i], ctx->test_node_id);
        
        if (ptr) {
            // Verify memory is accessible
            memset(ptr, 0xCC, large_sizes[i] > 1024 ? 1024 : large_sizes[i]);
            TEST_PASS_DEBUG(m, "Size %zu: Large allocation successful", large_sizes[i]);
            l0_kfree(ptr);
            passed++;
        } else {
            TEST_FAIL(m, "Size %zu: Large allocation failed", large_sizes[i]);
        }
    }
    
    TEST_END(m, "Passed: %d/%d tests", passed, total);
    return (passed == total) ? 0 : -1;
}

static struct test_case test_allocation_cases[] = {
    {"Small Object Allocation", test_small_object_allocation},
    {"Large Object Allocation", test_large_object_allocation},
};

DECLARE_TEST_MODULE(allocation, test_allocation_cases)